﻿#include "stdafx.h"
#include "AppHelper.h"

#include <QDir>
#include <QResource>
#include <QTextCodec>
#include <QTranslator>
#include <QApplication>

QSettings * gSettingConfig = NULL; 
QMap<QString, QVariant> gMapConfigs;

//==================================================================================================
struct QSettingGroup
{
	QSettingGroup(QSettings & config, const QString & group) : settings(config)
	{
		settings.beginGroup(group);
	}

	~QSettingGroup() { settings.endGroup(); }

	template< typename T > T Value(const QString & Key, const QVariant & Def = QVariant())
	{
		return settings.value(Key, Def).value< T >();
	}

	QStringList stringList(const QString & Key){ return Value< QStringList >(Key); }

	QByteArray byteArray(const QString & Key, const QVariant & Def = QVariant())
	{
		return Value< QByteArray >(Key, Def);
	}

	QString string(const QString & Key, const QVariant & Def = QVariant())
	{
		return Value< QString >(Key, Def);
	}

	int number(const QString & Key, const QVariant & Def = QVariant())
	{
		return Value< int >(Key, Def);
	}

	QSettings & settings;
};

//==================================================================================================
QSettings * getConfig()
{
	if (gSettingConfig == NULL)
	{
		QString appFile = QCoreApplication::applicationDirPath() + "/" + QCoreApplication::applicationName() + ".ini";
		gSettingConfig = new QSettings(appFile, QSettings::IniFormat);
	}

	return gSettingConfig;
}

void readConfig(QSettings & config)
{
	gMapConfigs.clear();
    const QStringList & listChild = config.allKeys();
	for (int i = 0; i < listChild.count(); ++i)
	{
		const QString & key = listChild.at(i);
		const QVariant & value = config.value(key);
		gMapConfigs.insert(key, value);
	}

}

void saveConfig(QSettings & config)
{
	config.clear();
	QMap<QString, QVariant>::const_iterator it;
	for (it = gMapConfigs.begin(); it != gMapConfigs.end(); ++it)
	{
		config.setValue(it.key(), it.value());
	}

}

//==================================================================================================
QString dirExpand(const char * path)
{ 
	return dirExpand(QString(path)); 
}

QString dirExpand(const QString & path)
{
	static QString appDir, binary, config;
	if (appDir.isEmpty() || appDir.isNull())
	{
		binary = QCoreApplication::applicationDirPath();
		appDir = QDir(binary + "/..").canonicalPath();
		config = appDir + "/etc";
	}

	QString temp(path);

	temp.replace("$(AppDir)", appDir);
	temp.replace("$(Binary)", binary);
	temp.replace("$(Config)", config);

	return temp;
}

QStringList dirExpand(const QStringList & pathList)
{
	typedef QStringList::const_iterator QStringListItr;
	QStringListItr Begin = pathList.begin();
	QStringListItr End = pathList.end();
	QStringList pathExpands;

	for (QStringListItr itr = Begin; itr != End; itr++)
	{
		pathExpands.append(dirExpand(*itr));
	}

	return pathExpands;
}

//==================================================================================================
void regResource(const QString & Name, const QString & Root)
{
	QString name(Name), root(Root);
	if (root[0] == ':'){ root[0] = '/'; }
	if (root[0] == '@'){ root[0] = '/'; }
	if (root[0] != '/'){ root.insert(0, '/'); }
	QResource::registerResource(dirExpand(name), root);
}

//==================================================================================================
void addTranslator(const QString & Name)
{
	QTranslator * translator = new QTranslator(0);
	translator->load(QString("lang:") + Name);
	qApp->installTranslator(translator);
}

void setSkinStyles(const QString & Name)
{
	QFile skinFile(QString("skin:") + Name);
	if(skinFile.open(QFile::ReadOnly | QFile::Unbuffered))
		qApp->setStyleSheet(skinFile.readAll());
	skinFile.close();
}

//==================================================================================================
static void initResourceSearch( QSettings & settings )
{
	QSettingGroup config( settings , "Search" );

	QStringList resDirs = settings.childKeys( );
	foreach( const QString & resDir , resDirs )
	{
        QStringList resPaths = config.stringList( resDir );
		QDir::setSearchPaths( resDir , dirExpand( resPaths ) );
	}
}

static void initResourceFiles(QSettings & settings)
{
	QSettingGroup config(settings, "Resource");

	QStringList resPaths = settings.childKeys();
	foreach(const QString & resRoot, resPaths)
	{
		QString resFile = config.string(resRoot);
		regResource(resFile, resRoot);
	}
}

static void initPluginsPaths(QSettings & settings)
{
	QSettingGroup config(settings, "Plugins");

	QStringList libraryPaths;
	QStringList listPaths = settings.childKeys();
	foreach(const QString & dirPath, listPaths)
	{
		libraryPaths += config.stringList(dirPath);
	}

	libraryPaths = dirExpand(libraryPaths);
	libraryPaths += qApp->libraryPaths();
	qApp->setLibraryPaths(libraryPaths);
}
 
static void initAppSettings(QSettings & settings)
{
	QSettingGroup config(settings, "Application");
	QByteArray codec = config.byteArray("LocaleCodec", "GB18030");
	QTextCodec::setCodecForLocale(QTextCodec::codecForName(codec));
	addTranslator(config.string("Language", "zh_CN"));
	setSkinStyles(config.string("Theme", "Default"));
}

//==================================================================================================
void initApplication()
{
	QSettings & config = * getConfig();
	QDir::setCurrent(dirExpand("$(AppDir)"));

	readConfig(config);
	initResourceSearch(config);
	initResourceFiles(config);
	initPluginsPaths(config);
	initAppSettings(config);

}

//==================================================================================================
QMap<QString, QStringList> getSeetingGroup(const QString & GroupName, const QString & FilePath)
{
	QString Path;
	QMap<QString, QStringList> Groups;

	if (FilePath.isEmpty())
	{
		Path = QCoreApplication::applicationDirPath() + "/" + QCoreApplication::applicationName() + ".ini";
	}

	QSettings settings(Path, QSettings::IniFormat);
	settings.setIniCodec(QTextCodec::codecForName("GB2312"));
	QSettingGroup config(settings, GroupName);
	QStringList keys = settings.childKeys();
	foreach(const QString & key, keys)
	{
        const QStringList & value = config.stringList(key);
		Groups.insert(key, value);
	}

	return Groups;
}

//==================================================================================================
QSignalsBlocker::QSignalsBlocker(QObject * object) : sender(object)
{
	if (sender) sender->blockSignals(true);
}

QSignalsBlocker::~QSignalsBlocker()
{
	if (sender) sender->blockSignals(false);
}

//==================================================================================================
QWaitCursor::QWaitCursor(QWidget * w) : widget(w)
{
	if (widget) widget->setCursor(QCursor(Qt::WaitCursor));
}

QWaitCursor::~QWaitCursor(void)
{
	if (widget) widget->unsetCursor();
}
